<!DOCTYPE html>
<html>
<head>
    

    

    
<!-- Baidu Tongji -->
<script>var _hmt = _hmt || []</script>
<script async src="//hm.baidu.com/hm.js?a7c05ce530152d9866930ef4850ee566"></script>
<!-- End Baidu Tongji -->




    <meta charset="utf-8">
    
    
    
    <title>全文检索技术Lucene6.6.0 | 神奇的鸭鸭の码农库 | 新知识要不断的总结记录成笔记，要多写，多画，能够清晰透彻的将知识讲给别人听，才是达到理解的层次。</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <meta name="theme-color" content="#765959">
    
    
    <meta name="keywords" content="全文检索">
    <meta name="description" content="Lucene介绍什么是LuceneLucene是apache下的一个开源的全文检索引擎工具包。它为软件开发人员提供一个简单易用的工具包（类库），以方便的在目标系统中实现全文检索的功能。 全文检索全文检索首先将要查询的目标文档中的词提取出来，组成索引，通过查询索引达到搜索目标文档的目的。这种先建立索引，再对索引进行搜索的过程就叫全文检索（Full-text Search）。 注意：Lucene和搜索">
<meta name="keywords" content="全文检索">
<meta property="og:type" content="article">
<meta property="og:title" content="全文检索技术Lucene6.6.0">
<meta property="og:url" content="http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/index.html">
<meta property="og:site_name" content="神奇的鸭鸭の码农库">
<meta property="og:description" content="Lucene介绍什么是LuceneLucene是apache下的一个开源的全文检索引擎工具包。它为软件开发人员提供一个简单易用的工具包（类库），以方便的在目标系统中实现全文检索的功能。 全文检索全文检索首先将要查询的目标文档中的词提取出来，组成索引，通过查询索引达到搜索目标文档的目的。这种先建立索引，再对索引进行搜索的过程就叫全文检索（Full-text Search）。 注意：Lucene和搜索">
<meta property="og:image" content="http://om6odecqr.bkt.clouddn.com/Lucene%E5%AE%9E%E7%8E%B0%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2%E7%9A%84%E6%B5%81%E7%A8%8B.png">
<meta property="og:image" content="http://om6odecqr.bkt.clouddn.com/book%E6%95%B0%E6%8D%AE%E5%BA%93%E6%88%AA%E5%9B%BE.png">
<meta property="og:image" content="http://om6odecqr.bkt.clouddn.com/%E7%B4%A2%E5%BC%95%E6%96%87%E4%BB%B6%E7%9A%84%E9%80%BB%E8%BE%91%E7%BB%93%E6%9E%84.png">
<meta property="og:image" content="http://om6odecqr.bkt.clouddn.com/%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E6%97%B6%E8%AE%BE%E7%BD%AEboost%E5%80%BC.png">
<meta property="og:updated_time" content="2017-12-05T09:58:29.758Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="全文检索技术Lucene6.6.0">
<meta name="twitter:description" content="Lucene介绍什么是LuceneLucene是apache下的一个开源的全文检索引擎工具包。它为软件开发人员提供一个简单易用的工具包（类库），以方便的在目标系统中实现全文检索的功能。 全文检索全文检索首先将要查询的目标文档中的词提取出来，组成索引，通过查询索引达到搜索目标文档的目的。这种先建立索引，再对索引进行搜索的过程就叫全文检索（Full-text Search）。 注意：Lucene和搜索">
<meta name="twitter:image" content="http://om6odecqr.bkt.clouddn.com/Lucene%E5%AE%9E%E7%8E%B0%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2%E7%9A%84%E6%B5%81%E7%A8%8B.png">
    
    <link rel="shortcut icon" href="/favicon.ico">
    <link rel="stylesheet" href="/css/style.css?v=1.4.3">
    <script>window.lazyScripts=[]</script>
</head>

<body>
    <div id="loading" class="active"></div>

    <aside id="menu" class="hide" >
  <div class="inner flex-row-vertical">
    <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menu-off">
        <i class="icon icon-lg icon-close"></i>
    </a>
    <div class="brand-wrap">
      <div class="brand">
        <a href="/" class="avatar waves-effect waves-circle waves-light">
          <img src="/img/avatar.jpg">
        </a>
        <hgroup class="introduce">
          <h5 class="nickname">神奇的鸭鸭</h5>
          <a href="mailto:702038338@qq.com" title="702038338@qq.com" class="mail">702038338@qq.com</a>
        </hgroup>
      </div>
    </div>
    <div class="scroll-wrap flex-col">
      <ul class="nav">
        
            <li class="waves-block waves-effect">
              <a href="/"  >
                <i class="icon icon-lg icon-home"></i>
                主页
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/archives"  >
                <i class="icon icon-lg icon-archives"></i>
                归档
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/tags"  >
                <i class="icon icon-lg icon-tags"></i>
                标签
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://git.oschina.net/magic_duck" target="_blank" >
                <i class="icon icon-lg icon-gg-circle"></i>
                码云
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://www.zhihu.com/people/shen-qi-de-ya-ya" target="_blank" >
                <i class="icon icon-lg icon-twitter"></i>
                知乎
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/404.html"  >
                <i class="icon icon-lg icon-link"></i>
                404页面测试
              </a>
            </li>
        
      </ul>
    </div>
  </div>
</aside>

    <main id="main">
        <header class="top-header" id="header">
    <div class="flex-row">
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light on" id="menu-toggle">
          <i class="icon icon-lg icon-navicon"></i>
        </a>
        <div class="flex-col header-title ellipsis">全文检索技术Lucene6.6.0</div>
        
        <div class="search-wrap" id="search-wrap">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
                <i class="icon icon-lg icon-chevron-left"></i>
            </a>
            <input type="text" id="key" class="search-input" autocomplete="off" placeholder="输入感兴趣的关键字">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="search">
                <i class="icon icon-lg icon-search"></i>
            </a>
        </div>
        
        
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menuShare">
            <i class="icon icon-lg icon-share-alt"></i>
        </a>
        
    </div>
</header>
<header class="content-header post-header">

    <div class="container fade-scale">
        <h1 class="title">全文检索技术Lucene6.6.0</h1>
        <h5 class="subtitle">
            
                <time datetime="2017-09-02T14:00:00.000Z" itemprop="datePublished" class="page-time">
  2017-09-02
</time>


            
        </h5>
    </div>

    

</header>


<div class="container body-wrap">
    
    <aside class="post-widget">
        <nav class="post-toc-wrap" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#Lucene介绍"><span class="post-toc-number">1.</span> <span class="post-toc-text">Lucene介绍</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#什么是Lucene"><span class="post-toc-number">1.1.</span> <span class="post-toc-text">什么是Lucene</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#全文检索"><span class="post-toc-number">1.2.</span> <span class="post-toc-text">全文检索</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#Lucene实现全文检索流程"><span class="post-toc-number">2.</span> <span class="post-toc-text">Lucene实现全文检索流程</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#索引流程和一些概念问题"><span class="post-toc-number">2.1.</span> <span class="post-toc-text">索引流程和一些概念问题</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#为什么要采集数据？"><span class="post-toc-number">2.1.1.</span> <span class="post-toc-text">为什么要采集数据？</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#什么是非结构化数据？"><span class="post-toc-number">2.1.2.</span> <span class="post-toc-text">什么是非结构化数据？</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#如何对结构化数据搜索？"><span class="post-toc-number">2.1.3.</span> <span class="post-toc-text">如何对结构化数据搜索？</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#如何对非结构化数据搜索？"><span class="post-toc-number">2.1.4.</span> <span class="post-toc-text">如何对非结构化数据搜索？</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#如何采集数据？"><span class="post-toc-number">2.1.5.</span> <span class="post-toc-text">如何采集数据？</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#网页采集和一些爬虫项目"><span class="post-toc-number">2.1.6.</span> <span class="post-toc-text">网页采集和一些爬虫项目</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#入门程序"><span class="post-toc-number">3.</span> <span class="post-toc-text">入门程序</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#环境准备"><span class="post-toc-number">3.1.</span> <span class="post-toc-text">环境准备</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#数据库采集："><span class="post-toc-number">3.2.</span> <span class="post-toc-text">数据库采集：</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#索引文件的逻辑结构"><span class="post-toc-number">3.3.</span> <span class="post-toc-text">索引文件的逻辑结构</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#文档域"><span class="post-toc-number">3.3.1.</span> <span class="post-toc-text">文档域</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#索引域"><span class="post-toc-number">3.3.2.</span> <span class="post-toc-text">索引域</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#倒排索引表"><span class="post-toc-number">3.3.3.</span> <span class="post-toc-text">倒排索引表</span></a></li></ol></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#创建索引"><span class="post-toc-number">3.4.</span> <span class="post-toc-text">创建索引</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#创建文档Document"><span class="post-toc-number">3.4.1.</span> <span class="post-toc-text">创建文档Document</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#创建分词器Analyzer"><span class="post-toc-number">3.4.2.</span> <span class="post-toc-text">创建分词器Analyzer</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#如何查看索引信息？"><span class="post-toc-number">3.4.3.</span> <span class="post-toc-text">如何查看索引信息？</span></a></li></ol></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#搜索流程"><span class="post-toc-number">3.5.</span> <span class="post-toc-text">搜索流程</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#Field域"><span class="post-toc-number">4.</span> <span class="post-toc-text">Field域</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#Field属性"><span class="post-toc-number">4.1.</span> <span class="post-toc-text">Field属性</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#Field常用类型"><span class="post-toc-number">4.2.</span> <span class="post-toc-text">Field常用类型</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#Field代码修改如下"><span class="post-toc-number">4.3.</span> <span class="post-toc-text">Field代码修改如下</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#索引维护"><span class="post-toc-number">5.</span> <span class="post-toc-text">索引维护</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#搜索-查询"><span class="post-toc-number">6.</span> <span class="post-toc-text">搜索(查询)</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#Query查询"><span class="post-toc-number">6.1.</span> <span class="post-toc-text">Query查询</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#QueryParser查询"><span class="post-toc-number">6.2.</span> <span class="post-toc-text">QueryParser查询</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#TopDocs"><span class="post-toc-number">6.3.</span> <span class="post-toc-text">TopDocs</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#相关度排序"><span class="post-toc-number">7.</span> <span class="post-toc-text">相关度排序</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#设置boost值影响相关度排序"><span class="post-toc-number">7.1.</span> <span class="post-toc-text">设置boost值影响相关度排序</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#在创建索引时设置"><span class="post-toc-number">7.1.1.</span> <span class="post-toc-text">在创建索引时设置</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#在查询索引时设置"><span class="post-toc-number">7.1.2.</span> <span class="post-toc-text">在查询索引时设置</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#中文分词器"><span class="post-toc-number">8.</span> <span class="post-toc-text">中文分词器</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#分词器介绍"><span class="post-toc-number">8.1.</span> <span class="post-toc-text">分词器介绍</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#使用中文分词器IKAnalyzer"><span class="post-toc-number">8.2.</span> <span class="post-toc-text">使用中文分词器IKAnalyzer</span></a></li></ol></li></ol>
        </nav>
    </aside>
    
<article id="post-Lucene6.6.0_primary_01"
  class="post-article article-type-post fade" itemprop="blogPost">

    <div class="post-card">
        <h1 class="post-card-title">全文检索技术Lucene6.6.0</h1>
        <div class="post-meta">
            <time class="post-time" title="2017年09月02日 22:00" datetime="2017-09-02T14:00:00.000Z"  itemprop="datePublished">2017-09-02</time>

            


            
<span id="busuanzi_container_page_pv" title="文章总阅读量" style='display:none'>
    <i class="icon icon-eye icon-pr"></i><span id="busuanzi_value_page_pv"></span>
</span>


            

        </div>
        <div class="post-content" id="post-content" itemprop="postContent">
            <h2 id="Lucene介绍"><a href="#Lucene介绍" class="headerlink" title="Lucene介绍"></a>Lucene介绍</h2><h3 id="什么是Lucene"><a href="#什么是Lucene" class="headerlink" title="什么是Lucene"></a>什么是Lucene</h3><p>Lucene是apache下的一个开源的全文检索引擎工具包。它为软件开发人员提供一个简单易用的工具包（类库），以方便的在目标系统中实现全文检索的功能。</p>
<h3 id="全文检索"><a href="#全文检索" class="headerlink" title="全文检索"></a>全文检索</h3><p>全文检索首先将要查询的目标文档中的词提取出来，组成索引，通过查询索引达到搜索目标文档的目的。这种先建立索引，再对索引进行搜索的过程就叫全文检索（Full-text Search）。</p>
<p><strong>注意：</strong>Lucene和搜索引擎是不同的，Lucene是一套用java或其它语言写的全文检索的工具包。它为应用程序提供了很多个api接口去调用，可以简单理解为是一套实现全文检索的类库。搜索引擎是一个全文检索系统，它是一个单独运行的软件系统。</p>
<h2 id="Lucene实现全文检索流程"><a href="#Lucene实现全文检索流程" class="headerlink" title="Lucene实现全文检索流程"></a>Lucene实现全文检索流程</h2><p>全文检索的流程分为两大部分：索引流程、搜索流程：<br><img src="http://om6odecqr.bkt.clouddn.com/Lucene%E5%AE%9E%E7%8E%B0%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2%E7%9A%84%E6%B5%81%E7%A8%8B.png" alt="Lucene实现全文检索流程"></p>
<p><strong>索引流程：</strong>采集数据——构建文档对象——分析文档(分词)——搜索流程</p>
<p><strong>搜索流程：</strong>用户通过搜索界面——创建查询——执行搜索——搜索器从索引库搜索——渲染搜索结果</p>
<h3 id="索引流程和一些概念问题"><a href="#索引流程和一些概念问题" class="headerlink" title="索引流程和一些概念问题"></a>索引流程和一些概念问题</h3><p>对文档索引的过程，就是将用户要搜索的文档内容进行索引，然后把索引存储在索引库(index)中。</p>
<h4 id="为什么要采集数据？"><a href="#为什么要采集数据？" class="headerlink" title="为什么要采集数据？"></a>为什么要采集数据？</h4><p>全文检索要搜索的数据信息格式多种多样，拿搜索引擎(百度，google)来说，通过搜索引擎网站能搜索互联网站上的网页(html)、互联网上的音乐(mp3..)、视频(avi..)、pdf电子书等。<strong>全文检索搜索的这些数据称为非结构化数据。</strong></p>
<h4 id="什么是非结构化数据？"><a href="#什么是非结构化数据？" class="headerlink" title="什么是非结构化数据？"></a>什么是非结构化数据？</h4><ul>
<li>结构化数据：指具有固定格式或有限长度的数据，如数据库，元数据等。</li>
<li>非结构化数据：指不定长或无固定格式的数据，如邮件，word文档等。</li>
</ul>
<h4 id="如何对结构化数据搜索？"><a href="#如何对结构化数据搜索？" class="headerlink" title="如何对结构化数据搜索？"></a>如何对结构化数据搜索？</h4><p>由于结构化数据是固定格式，所以可以针对固定格式的数据设计算法来搜索，比如数据库like查询，like查询采用顺序扫描法，使用关键字匹配内容，对于内容量大的like查询速度慢。</p>
<h4 id="如何对非结构化数据搜索？"><a href="#如何对非结构化数据搜索？" class="headerlink" title="如何对非结构化数据搜索？"></a>如何对非结构化数据搜索？</h4><p>需要将所有要搜索的非结构化数据通过技术手段采集到一个固定的地方，将这些非结构化的数据想办法组成结构化的数据，再以一定算法去搜索。</p>
<h4 id="如何采集数据？"><a href="#如何采集数据？" class="headerlink" title="如何采集数据？"></a>如何采集数据？</h4><ul>
<li>对于互联网上网页采用http将网页抓取到本地生成html文件</li>
<li>如果数据在数据库中就连接数据库读取表中的数据</li>
<li>如果数据是文件系统中的某个文件，就通过文件系统读取文件的内容</li>
</ul>
<h4 id="网页采集和一些爬虫项目"><a href="#网页采集和一些爬虫项目" class="headerlink" title="网页采集和一些爬虫项目"></a>网页采集和一些爬虫项目</h4><p>因为目前搜索引擎主要搜索数据的来源是互联网，搜索引擎使用一种爬虫程序抓取网页（ 通过http抓取html网页信息），以下是一些爬虫项目：</p>
<ul>
<li>solr是apache的一个子项目，支持从关系数据库、xml文档中提取原始数据。</li>
<li>Nutch是apache的一个子项目，包括大规模爬虫工具，能够抓取和分辨web网站数据。</li>
<li>jsoup 是一款Java 的HTML解析器，可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API，可通过DOM，CSS以及类似于jQuery的操作方法来取出和操作数据。</li>
<li>Heritrix 是一个由 java 开发的、开源的网络爬虫，用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性，方便用户实现自己的抓取逻辑。</li>
</ul>
<hr>
<h2 id="入门程序"><a href="#入门程序" class="headerlink" title="入门程序"></a>入门程序</h2><p><strong>需求：</strong>使用Lucene实现电商项目中图书类商品的索引和搜索功能，针对电商站内搜索功能，全文检索的数据源在数据库中，需要通过jdbc访问数据库中<strong>book表</strong>的内容。<br><img src="http://om6odecqr.bkt.clouddn.com/book%E6%95%B0%E6%8D%AE%E5%BA%93%E6%88%AA%E5%9B%BE.png" alt="book表"></p>
<h3 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h3><p>下载<a href="http://lucene.apache.org/" target="_blank" rel="external">lucene6.6.0</a>，JDK最低要求1.7以上。</p>
<p>创建java工程，添加如下jar包：</p>
<ul>
<li>mysql驱动包</li>
<li>lucene核心包 lucene-core.jar</li>
<li>分析器通用包 lucene-analyzers-common.jar</li>
<li>查询解析器包 lucene-queryparser.jar</li>
<li>junit包 junit.jar(赠送包)</li>
</ul>
<h3 id="数据库采集："><a href="#数据库采集：" class="headerlink" title="数据库采集："></a>数据库采集：</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// Po</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Book</span> </span>&#123;</div><div class="line">	<span class="keyword">private</span> Integer id;<span class="comment">// 图书ID</span></div><div class="line">	<span class="keyword">private</span> String name;<span class="comment">// 图书名称</span></div><div class="line">	<span class="keyword">private</span> Float price;<span class="comment">// 图书价格</span></div><div class="line">	<span class="keyword">private</span> String pic;<span class="comment">// 图书图片</span></div><div class="line">	<span class="keyword">private</span> String description;<span class="comment">// 图书描述</span></div><div class="line">&#125;</div><div class="line"><span class="comment">// Dao</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BookDaoImpl</span> <span class="keyword">implements</span> <span class="title">BookDao</span> </span>&#123;</div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">public</span> List&lt;Book&gt; <span class="title">queryBookList</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">        List&lt;Book&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</div><div class="line">        <span class="comment">// 数据库连接、预编译statement、结果集</span></div><div class="line">        Connection connection = <span class="keyword">null</span>;</div><div class="line">        PreparedStatement prepareStatement = <span class="keyword">null</span>;</div><div class="line">        ResultSet resultSet = <span class="keyword">null</span>;</div><div class="line">        <span class="keyword">try</span> &#123;</div><div class="line">            Class.forName(<span class="string">"com.mysql.jdbc.Driver"</span>);</div><div class="line">            connection = DriverManager.getConnection(<span class="string">"jdbc:mysql://localhost:3306/solr"</span>, <span class="string">"root"</span>, <span class="string">"sqdyy.214"</span>);</div><div class="line">            String sql = <span class="string">"select * from book"</span>;</div><div class="line">            prepareStatement = connection.prepareStatement(sql);</div><div class="line">            resultSet = prepareStatement.executeQuery();</div><div class="line">            <span class="comment">// 结果集解析</span></div><div class="line">            <span class="keyword">while</span> (resultSet.next()) &#123;</div><div class="line">                Book book = <span class="keyword">new</span> Book();</div><div class="line">                book.setId(resultSet.getInt(<span class="string">"id"</span>));</div><div class="line">                book.setName(resultSet.getString(<span class="string">"name"</span>));</div><div class="line">                book.setPrice(resultSet.getFloat(<span class="string">"price"</span>));</div><div class="line">                book.setPic(resultSet.getString(<span class="string">"pic"</span>));</div><div class="line">                book.setDescription(resultSet.getString(<span class="string">"description"</span>));</div><div class="line">                list.add(book);</div><div class="line">            &#125;</div><div class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</div><div class="line">            e.printStackTrace();</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">return</span> list;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="索引文件的逻辑结构"><a href="#索引文件的逻辑结构" class="headerlink" title="索引文件的逻辑结构"></a>索引文件的逻辑结构</h3><p><img src="http://om6odecqr.bkt.clouddn.com/%E7%B4%A2%E5%BC%95%E6%96%87%E4%BB%B6%E7%9A%84%E9%80%BB%E8%BE%91%E7%BB%93%E6%9E%84.png" alt="索引文件的逻辑结构"></p>
<h4 id="文档域"><a href="#文档域" class="headerlink" title="文档域"></a>文档域</h4><p>对非结构化的数据统一格式为document文档格式，一个文档有多个field域，不同的文档其field的个数可以不同，建议相同类型的文档包括相同的field。<strong>本例中一个document对应一条book表的记录</strong>。</p>
<h4 id="索引域"><a href="#索引域" class="headerlink" title="索引域"></a>索引域</h4><p>用于搜索，搜索程序将从索引域中搜索一个一个词，根据词找到对应的文档。将Document中的Field的内容进行分词，将分好的词创建索引，索引=Field域名:词。</p>
<h4 id="倒排索引表"><a href="#倒排索引表" class="headerlink" title="倒排索引表"></a>倒排索引表</h4><p>传统方法是先找到文件，然后在文件中找内容，在文件内容中匹配搜索关键字，这种方法是顺序扫描方法，数据量大就搜索慢。</p>
<p>倒排索引结构是根据内容（词语）找文档，倒排索引结构也叫反向索引结构，包括索引和文档两部分，索引即词汇表，它是在索引中匹配搜索关键字，由于索引内容量有限并且采用固定优化算法搜索速度很快，找到了索引中的词汇，词汇与文档关联，从而最终找到了文档。</p>
<h3 id="创建索引"><a href="#创建索引" class="headerlink" title="创建索引"></a>创建索引</h3><p>创建索引的流程：[文档Document]——[分词器Analyzer]——[索引写对象IndexWriter]——[索引目录流对象Directory]——[索引库]</p>
<p><strong>IndexWriter</strong>是索引过程的核心组件，通过IndexWriter可以<strong>创建新索引，更新索引，删除索引</strong>操作。IndexWriter需要通过<strong>Directory</strong>对索引进行存储操作。</p>
<p><strong>Directory</strong>描述了索引的存储位置，底层封装了I/O操作，负责对索引进行存储。它是一个抽象类，它的子类常用的包括FSDirectory(文件系统存储索引)、RAMDirectory(内存存储索引)。</p>
<h4 id="创建文档Document"><a href="#创建文档Document" class="headerlink" title="创建文档Document"></a>创建文档Document</h4><p>采集数据的目的是为了索引，在索引前需要将原始内容创建成文档(Document)，文档(Document)中包括一个一个的域(field)：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">createIndex</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    <span class="comment">// 采集数据</span></div><div class="line">    BookDao dao = <span class="keyword">new</span> BookDaoImpl();</div><div class="line">    List&lt;Book&gt; DataList = dao.queryBookList();</div><div class="line">    <span class="comment">// Document对象集合</span></div><div class="line">    List&lt;Document&gt; docList = <span class="keyword">new</span> ArrayList&lt;&gt;();</div><div class="line">    Document doc = <span class="keyword">null</span>;</div><div class="line">    <span class="keyword">for</span> (Book book : DataList) &#123;</div><div class="line">        <span class="comment">// 创建Document对象，同时要创建field对象</span></div><div class="line">        doc = <span class="keyword">new</span> Document();</div><div class="line">        <span class="comment">// 更具不同需求创建不同Field store:如果是yes，则说明存储到文档域中</span></div><div class="line">        Field id = <span class="keyword">new</span> TextField(<span class="string">"id"</span>, book.getId().toString(), Store.YES);</div><div class="line">        Field name = <span class="keyword">new</span> TextField(<span class="string">"name"</span>, book.getName(), Store.YES);</div><div class="line">        Field price = <span class="keyword">new</span> TextField(<span class="string">"price"</span>, book.getPrice().toString(), Store.YES);</div><div class="line">        Field pic = <span class="keyword">new</span> TextField(<span class="string">"pic"</span>, book.getPic(), Store.YES);</div><div class="line">        Field description = <span class="keyword">new</span> TextField(<span class="string">"description"</span>, book.getDescription(), Store.YES);</div><div class="line">        <span class="comment">// 将field域设置到Document对象中</span></div><div class="line">        doc.add(id);</div><div class="line">        doc.add(name);</div><div class="line">        doc.add(price);</div><div class="line">        doc.add(pic);</div><div class="line">        doc.add(description);</div><div class="line"></div><div class="line">        docList.add(doc);</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<h4 id="创建分词器Analyzer"><a href="#创建分词器Analyzer" class="headerlink" title="创建分词器Analyzer"></a>创建分词器Analyzer</h4><p>在创建之前先了解下分词过程：</p>
<p>在对Document中的内容生成索引之前需要使用分词器进行分词，主要过程就是分词，过滤两步。<strong>分词</strong>就是将采集的文档内容切分成一个一个的词，具体应该说是将Document中Field的value值切分成一个一个的词。<strong>过滤</strong>包括去除标点符号、去除停用词(的、是、a、an、the等)、大写转小写、词的形还原(复数形式转成单数形参、过去式转成现在式等)等。</p>
<p>停用词是为节省存储空间和提高搜索效率，搜索引擎在索引页面或处理搜索请求时会自动忽略某些字或词，这些字或词即被称为Stop Words(停用词)。比如语气助词、副词、介词、连接词等，通常自身并无明确的意义，只有将其放入一个完整的句子中才有一定作用，如常见的“的”、“在”、“是”、“啊”等。</p>
<p>Lucene作为一个工具包，提供不同国家的分词器，详情可以查看lucene-analyzers-common-6.6.0.jar下的包，注意由于语言不同分词器的切分规则也不同，本例中使用StandardAnalyzer，它可以对英文进行分词。</p>
<p>如下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源码(可以看到语汇单元的生成过程)：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">protected</span> TokenStreamComponents <span class="title">createComponents</span><span class="params">(<span class="keyword">final</span> String fieldName, <span class="keyword">final</span> Reader reader)</span> </span>&#123;</div><div class="line">    <span class="comment">// Tokenizer是一个标准分词器，负责将原始reader转换为语汇单元即进行分词，Lucene提供了很多分词器，也可以使用第三方的分词，比如jcseg(一个中文分词器)。</span></div><div class="line">    <span class="keyword">final</span> StandardTokenizer src = <span class="keyword">new</span> StandardTokenizer(getVersion(), reader);</div><div class="line">    src.setMaxTokenLength(maxTokenLength);</div><div class="line">    <span class="comment">// 创建TokenStream，会进行标准过滤</span></div><div class="line">    TokenStream tok = <span class="keyword">new</span> StandardFilter(getVersion(), src);</div><div class="line">    <span class="comment">// 大写转小写过滤</span></div><div class="line">    tok = <span class="keyword">new</span> LowerCaseFilter(getVersion(), tok);</div><div class="line">    <span class="comment">// 停用词过滤</span></div><div class="line">    tok = <span class="keyword">new</span> StopFilter(getVersion(), tok, stopwords);</div><div class="line">    <span class="comment">// 最终生成语汇单元Token</span></div><div class="line">    <span class="keyword">return</span> <span class="keyword">new</span> TokenStreamComponents(src, tok) &#123;</div><div class="line">        <span class="meta">@Override</span></div><div class="line">        <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">setReader</span><span class="params">(<span class="keyword">final</span> Reader reader)</span> <span class="keyword">throws</span> IOException </span>&#123;</div><div class="line">            src.setMaxTokenLength(StandardAnalyzer.<span class="keyword">this</span>.maxTokenLength);</div><div class="line">            <span class="keyword">super</span>.setReader(reader);</div><div class="line">        &#125;</div><div class="line">    &#125;;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>比如<strong>Lucene is a Java full-text search engine.</strong>这个文档经过分析器分析，会得到的语汇单元是：<strong>lucene、java、full、text、search、engine</strong>。同一个域中相同的语汇单元(Tocken)对应同一个Term(词)，它记录了语汇单元的内容及所在域的域名等。<strong>不同的域中拆分出来的相同的单词对应不同的term</strong>，<strong>相同的域中拆分出来的相同的单词对应相同的term</strong>。例如，图书信息里面，图书名称中的java和图书描述中的java对应不同的term。</p>
<p>代码实现：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 采集数据——创建文档——分析文档</span></div><div class="line"><span class="comment">// 创建分词器——标准分词器</span></div><div class="line">Analyzer analyzer = <span class="keyword">new</span> StandardAnalyzer();</div><div class="line"></div><div class="line"><span class="comment">// 创建 索引写对象IndexWriter        </span></div><div class="line">IndexWriterConfig IndexWriterConfig = <span class="keyword">new</span> IndexWriterConfig(analyzer);</div><div class="line">Path path = <span class="keyword">new</span> File(<span class="string">"E:\\MyCode\\Eclipse\\luceneTest1\\LuceneDirectory"</span>).toPath();</div><div class="line">Directory directory = FSDirectory.open(path);</div><div class="line">IndexWriter indexWriter = <span class="keyword">new</span> IndexWriter(directory, IndexWriterConfig);</div><div class="line"></div><div class="line"><span class="comment">// 通过 索引写对象将 Document写入到索引库中</span></div><div class="line"><span class="keyword">for</span> (Document document : docList) &#123;</div><div class="line">    indexWriter.addDocument(document);</div><div class="line">&#125;</div><div class="line"><span class="comment">// 关闭IndexWriter</span></div><div class="line">indexWriter.close();</div></pre></td></tr></table></figure></p>
<h4 id="如何查看索引信息？"><a href="#如何查看索引信息？" class="headerlink" title="如何查看索引信息？"></a>如何查看索引信息？</h4><p>使用Luke，Luke作为Lucene工具包中的一个工具<a href="https://github.com/DmitryKey/luke，可以通过界面来进行索引文件的查询，修改。" target="_blank" rel="external">https://github.com/DmitryKey/luke，可以通过界面来进行索引文件的查询，修改。</a></p>
<h3 id="搜索流程"><a href="#搜索流程" class="headerlink" title="搜索流程"></a>搜索流程</h3><p>搜索流程：[用户查询Query]——[索引搜索对象IndexSearcher]——[索引读取对象IndexReader]——[索引目录流对象Directory]——[索引库] [回到索引搜索对象,返回结果集TopDocs]</p>
<p>同数据库的sql一样，lucene全文检索也有固定的语法如AND,OR,NOT等，举个例子，用户想找一个description中包括java关键字和Lucene关键字的文档。它对应的查询语句应该是<strong>description:java AND lucene</strong>。</p>
<p>搜索索引，根据关键字从索引中找到对应的索引信息，即找到词Term，Term与Document相关联，找到了Term就找到了关联的Document，从Document取出Field中的信息即是要搜索的信息，其代码实现如下：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">indexSearch</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    <span class="comment">// 创建query解析对象</span></div><div class="line">    <span class="comment">// 使用QueryParser搜索时，需要指定分词器，且搜索时的分词器要和索引时的分词器一致</span></div><div class="line">    QueryParser parser = <span class="keyword">new</span> QueryParser(<span class="string">"description"</span>, <span class="keyword">new</span> StandardAnalyzer());</div><div class="line">    <span class="comment">// 通过queryparser来创建query对象</span></div><div class="line">    <span class="comment">// 参数：输入的lucene的查询语句(关键字一定要大写)</span></div><div class="line">    Query query = parser.parse(<span class="string">"description:java OR lucene"</span>);</div><div class="line"></div><div class="line">    Path path = <span class="keyword">new</span> File(<span class="string">"E:\\MyCode\\Eclipse\\luceneTest1\\LuceneDirectory"</span>).toPath();</div><div class="line">    <span class="comment">// 创建 索引目录流对象Directory</span></div><div class="line">    Directory directory = FSDirectory.open(path);</div><div class="line">    <span class="comment">// 创建 索引读取对象IndexReader</span></div><div class="line">    IndexReader reader = DirectoryReader.open(directory);</div><div class="line">    <span class="comment">// 创建 索引搜索对象IndexSearcher</span></div><div class="line">    IndexSearcher searcher = <span class="keyword">new</span> IndexSearcher(reader);</div><div class="line"></div><div class="line">    <span class="comment">// 通过searcher来搜索索引库 返回结果集TopDocs</span></div><div class="line">    <span class="comment">// 第二个参数：指定需要显示的顶部记录的N条</span></div><div class="line">    TopDocs topDocs = searcher.search(query, <span class="number">10</span>);</div><div class="line">    <span class="comment">// 根据查询条件匹配出的记录总数</span></div><div class="line">    <span class="keyword">int</span> count = topDocs.totalHits;</div><div class="line">    System.out.println(<span class="string">"总记录数"</span> + count);</div><div class="line">    <span class="comment">// 根据查询条件匹配出的记录</span></div><div class="line">    ScoreDoc[] scoreDocs = topDocs.scoreDocs;</div><div class="line">    <span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) &#123;</div><div class="line">        <span class="comment">// 通过ID获得文档</span></div><div class="line">        <span class="keyword">int</span> docId = scoreDoc.doc;</div><div class="line">        Document doc = searcher.doc(docId);</div><div class="line">        System.out.println(<span class="string">"商品ID："</span> + doc.get(<span class="string">"id"</span>));</div><div class="line">        System.out.println(<span class="string">"商品名称："</span> + doc.get(<span class="string">"name"</span>));</div><div class="line">        System.out.println(<span class="string">"商品价格："</span> + doc.get(<span class="string">"price"</span>));</div><div class="line">        System.out.println(<span class="string">"商品图片地址："</span> + doc.get(<span class="string">"pic"</span>));</div><div class="line">        System.out.println(<span class="string">"=========================="</span>);</div><div class="line">        System.out.println(doc.get(<span class="string">"description"</span>));</div><div class="line">    &#125;</div><div class="line">    reader.close();</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<hr>
<h2 id="Field域"><a href="#Field域" class="headerlink" title="Field域"></a>Field域</h2><p>Field是文档中的域，包括Field名和Field值两部分，一个文档可以包括多个Field，Document只是Field的一个载体，Field值即为要索引的内容，也是要搜索的内容。</p>
<h3 id="Field属性"><a href="#Field属性" class="headerlink" title="Field属性"></a>Field属性</h3><table>
<thead>
<tr>
<th style="text-align:left">属性</th>
<th style="text-align:left">是</th>
<th style="text-align:left">否</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">是否分词(tokenized)</td>
<td style="text-align:left">作分词处理，即将Field值进行分词，分词的目的是为了索引。比如商品名称，商品简介等，这些内容用户要输入关键字搜索，由于搜索的内容格式大、内容多需要分词后将语汇单元索引。</td>
<td style="text-align:left">不作分词处理。比如商品ID，文件路径，图片路径，不用作为查询条件的不用索引。</td>
</tr>
<tr>
<td style="text-align:left">是否存储(stored)</td>
<td style="text-align:left">将Field值存储在文档中，存储在文档中的Field才可以从Document中获取。比如商品名称，订单号，凡是将来要从Document中获取的Field都要存储。</td>
<td style="text-align:left">不存储Field值，不存储的Field无法通过Document获取。比如商品简介，内容较大不用存储。如果要向用户展示商品简介可以从系统的关系数据库中获取商品简介。</td>
</tr>
<tr>
<td style="text-align:left">是否索引(indexed)</td>
<td style="text-align:left">行索引。将Field分词后的词或整个Field值进行索引，索引的目的是为了搜索。比如商品名称，商品简介分析后进行索引，订单号，身份证号不用分析但也要索引，这些将来都要作为查询条件。</td>
<td style="text-align:left">不索引。该域的内容无法搜索到。比如：商品id，文件路径，图片路径等，不用作为查询条件的不用索引。</td>
</tr>
</tbody>
</table>
<h3 id="Field常用类型"><a href="#Field常用类型" class="headerlink" title="Field常用类型"></a>Field常用类型</h3><p>下面列出了开发中常用 的Filed类型，注意Field的属性，根据需求选择：<br>| Field类 | 数据类型 | Analyzed是否分词 | Indexed是否索引 | Stored是否存储 | 说明 |<br>| :——– | :——–| :——–| :——–| :——–| :——–|<br>| StringField(FieldName,FieldValue,Store.YES)) | 字符串 | N | Y | Y/N |这个Field用来构建一个字符串Field，但是不会进行分词，会将整个串存储在索引中，比如(订单号,身份证号等) |<br>| LongField(FieldName,FieldValue,Store.YES) | Long型 | Y | Y | Y/N | 这个Field用来构建一个Long数字型Field，进行分词和索引，比如(价格) |<br>| StoredField(FieldName,FieldValue) | 重载方法，支持多种类型 | N | N | Y | 这个Field用来构建不同类型Field不分析，不索引，但要Field存储在文档中 |<br>| TextField(FieldName,FieldValue,Store.NO)/TextField(FieldName,Reader) | 字符串/流 | Y | Y | Y/N | 如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略. |</p>
<h3 id="Field代码修改如下"><a href="#Field代码修改如下" class="headerlink" title="Field代码修改如下"></a>Field代码修改如下</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 根据不同需求创建不同Field store:如果是yes，则说明存储到文档域中</span></div><div class="line"><span class="comment">// 图书ID 不分词，要索引，要存储 StringField</span></div><div class="line">Field id = <span class="keyword">new</span> StringField(<span class="string">"id"</span>, book.getId().toString(), Store.YES);</div><div class="line"><span class="comment">// 图书名称 要分词，要索引，要存储 TextField</span></div><div class="line">Field name = <span class="keyword">new</span> TextField(<span class="string">"name"</span>, book.getName(), Store.YES);</div><div class="line"><span class="comment">// 图书价格 要分词、要索引、要存储 但是是数字类型，所以用LegacyFloatField</span></div><div class="line">Field price = <span class="keyword">new</span> LegacyFloatField(<span class="string">"price"</span>, book.getPrice(),Store.YES);</div><div class="line"><span class="comment">// 图书图片地址  不分词，不索引，要存储 StoredField</span></div><div class="line">Field pic = <span class="keyword">new</span> StoredField(<span class="string">"pic"</span>, book.getPic());</div><div class="line"><span class="comment">// 图书描述 要分词，要索引，不存储 TextField</span></div><div class="line">Field description = <span class="keyword">new</span> TextField(<span class="string">"description"</span>, book.getDescription(), Store.NO);</div></pre></td></tr></table></figure>
<hr>
<h2 id="索引维护"><a href="#索引维护" class="headerlink" title="索引维护"></a>索引维护</h2><p>管理人员通过电商系统更改图书信息，这时更新的是数据库，如果使用lucene搜索图书信息需要在数据库表book信息变化时及时更新lucene索引库。</p>
<p>添加索引(调用 indexWriter.addDocument(doc) 添加索引)</p>
<p>删除指定索引：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 根据Term项删除索引，满足条件的将全部删除</span></div><div class="line"><span class="comment">// Term是索引域中最小的单位。根据条件删除时，建议根据唯一键来进行删除。在solr中就是根据ID来进行删除和修改操作的。</span></div><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">deleteIndex</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    <span class="comment">// 指定索引库目录</span></div><div class="line">    Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">"E:\\MyCode\\Eclipse\\luceneTest1\\LuceneDirectory"</span>).toPath());</div><div class="line">    <span class="comment">// 创建IndexWriterConfig</span></div><div class="line">    IndexWriterConfig cfg = <span class="keyword">new</span> IndexWriterConfig(<span class="keyword">new</span> StandardAnalyzer());</div><div class="line">    <span class="comment">// 创建IndexWriter</span></div><div class="line">    IndexWriter indexWriter = <span class="keyword">new</span> IndexWriter(directory, cfg);</div><div class="line">    <span class="comment">// 通过IndexWriter来删除索引</span></div><div class="line">    indexWriter.deleteDocuments(<span class="keyword">new</span> Term(<span class="string">"id"</span>,<span class="string">"1"</span>));</div><div class="line">    <span class="comment">// 关流</span></div><div class="line">    indexWriter.close();</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>删除所有索引(indexWriter.deleteAll();)：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 将索引目录的索引信息全部删除，直接彻底删除，无法恢复。慎用！！！</span></div><div class="line">indexWriter.deleteAll();</div></pre></td></tr></table></figure></p>
<p>修改索引(更新索引是先删除再添加，建议对更新需求采用此方法并且要保证对已存在的索引执行更新，可以先查询出来，确定更新记录存在更新操作)：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 第一个参数：指定查询条件</span></div><div class="line"><span class="comment">// 第二个参数：修改后的对象</span></div><div class="line"><span class="comment">// 修改时如果根据查询条件，可以查询出结果，则将以前的删除，然后覆盖新的Document对象，如果没有查询出结果，则新增一个Document</span></div><div class="line"><span class="comment">// 修改流程：先查询，再删除，再添加</span></div><div class="line">Document doc = <span class="keyword">new</span> Document();</div><div class="line">doc.add(<span class="keyword">new</span> StringField(<span class="string">"name"</span>, <span class="string">"lisi"</span>, Store.YES));</div><div class="line">indexWriter.updateDocument(<span class="keyword">new</span> Term(<span class="string">"name"</span>,<span class="string">"zhangsan"</span>), doc);</div></pre></td></tr></table></figure></p>
<hr>
<h2 id="搜索-查询"><a href="#搜索-查询" class="headerlink" title="搜索(查询)"></a>搜索(查询)</h2><p>对于要搜索的信息创建Query查询对象，Lucene会根据Query查询对象生成最终的查询语法。类似关系数据库SQL语法一样，Lucene也有自己的查询语法，比如：”name:lucene”，表示查询Field的name名为”Lucene”的文档信息。可以通过两种方法创建查询对象：</p>
<p><strong>1 使用Lucene提供的Query子类</strong>，Query是一个抽象类，Lucene提供了很多查询对象，比如TermQuery项精确查询，NumericRangeQuery数字范围查询等。</p>
<p><strong>2 使用QueryParse解析查询表达式</strong>，QueryParse会将用户输入的查询表达式解析成Query对象实例。创建时需要指定分词器Analyzer，然后调用parse(String)方法。</p>
<h3 id="Query查询"><a href="#Query查询" class="headerlink" title="Query查询"></a>Query查询</h3><p>TermQuery查询，不使用分词器，搜索关键字作为整体来匹配Field域中的词解析查询，比如订单号，分类ID号等：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">termQuery</span><span class="params">()</span> </span>&#123;</div><div class="line">    Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">"description"</span>, <span class="string">"lucene"</span>));</div><div class="line">    doSearch(query);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>NumericRangeQuery查询，数字范围查询：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">numericRangeQuery</span><span class="params">()</span> </span>&#123;</div><div class="line">    <span class="comment">// 参数：域的名称 最小值 最大值 是否包含最小值 是否包含最大值</span></div><div class="line">    Query query = LegacyNumericRangeQuery.newFloatRange(<span class="string">"price"</span>, <span class="number">55f</span>, <span class="number">66f</span>, <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line">    doSearch(query);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>BooleanQuery组合查询：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">booleanQuery</span><span class="params">()</span> </span>&#123;</div><div class="line">    Builder builder = <span class="keyword">new</span> BooleanQuery.Builder();</div><div class="line">    Query q1 = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">"description"</span>, <span class="string">"lucene"</span>));</div><div class="line">    Query q2 = LegacyNumericRangeQuery.newFloatRange(<span class="string">"price"</span>, <span class="number">33f</span>, <span class="number">66f</span>, <span class="keyword">true</span>, <span class="keyword">false</span>);</div><div class="line">    builder.add(<span class="keyword">new</span> BooleanClause(q1, Occur.MUST));</div><div class="line">    builder.add(<span class="keyword">new</span> BooleanClause(q2, Occur.MUST));</div><div class="line">    <span class="comment">// 组合关系代表如下：</span></div><div class="line">    <span class="comment">// 1、MUST和MUST表示“与”的关系，即“并集”。 </span></div><div class="line">    <span class="comment">// 2、MUST和MUST_NOT前者包含后者不包含。 </span></div><div class="line">    <span class="comment">// 3、MUST_NOT和MUST_NOT没意义 </span></div><div class="line">    <span class="comment">// 4、SHOULD与MUST表示MUST，SHOULD失去意义； </span></div><div class="line">    <span class="comment">// 5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。 </span></div><div class="line">    <span class="comment">// 6、SHOULD与SHOULD表示“或”的概念。</span></div><div class="line">    doSearch(builder.build());</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<h3 id="QueryParser查询"><a href="#QueryParser查询" class="headerlink" title="QueryParser查询"></a>QueryParser查询</h3><p>通过QueryParser也可以创建Query，QueryParser提供一个parse(String)方法，此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过syso(query)查询。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 入门程序已经介绍</span></div><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testQueryParse</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    QueryParser queryParse = <span class="keyword">new</span> QueryParser(<span class="string">"name"</span>, <span class="keyword">new</span> StandardAnalyzer());</div><div class="line">    <span class="comment">// 指定查询语法，如果不指定，就搜索默认的域</span></div><div class="line">    Query query = queryParse.parse(<span class="string">"lucene"</span>);</div><div class="line">    System.out.println(query);<span class="comment">//name:lucene</span></div><div class="line">    doSearch(query);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>查询语法：</p>
<ul>
<li>基础的查询语法，关键词查询：域名:搜索的关键字</li>
<li>范围查询，域名:[最小值 TO 最大值]</li>
<li>组合条件查询：</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:left"></th>
<th style="text-align:left"></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Occur.MUST 查询条件必须满足，相当于and</td>
<td style="text-align:left">+（加号）</td>
</tr>
<tr>
<td style="text-align:left">Occur.SHOULD 查询条件可选，相当于or</td>
<td style="text-align:left">空格</td>
</tr>
<tr>
<td style="text-align:left">Occur.MUST_NOT 查询条件不能满足，相当于not非</td>
<td style="text-align:left">-（减号）</td>
</tr>
</tbody>
</table>
<p><strong>注意：QueryParser不支持对数字范围的搜索，它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。</strong><br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMultiFieldQueryParse</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    <span class="comment">// 可以指定默认搜索的域是多个</span></div><div class="line">    String[] fields = &#123;<span class="string">"name"</span>,<span class="string">"description"</span>&#125;;</div><div class="line">    MultiFieldQueryParser mfParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> StandardAnalyzer());</div><div class="line">    Query query = mfParser.parse(<span class="string">"lucene"</span>);</div><div class="line">    System.out.println(query);<span class="comment">//name:lucene description:lucene = name:lucene OR description:lucene</span></div><div class="line">    doSearch(query);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<h3 id="TopDocs"><a href="#TopDocs" class="headerlink" title="TopDocs"></a>TopDocs</h3><p>Lucene搜索结果可通过TopDocs遍历，TopDocs类提供了少量的属性，如下：</p>
<ul>
<li>Search方法需要指定匹配记录数量n：indexSearcher.search(Query,n);</li>
<li>TopDocs.totalHits：是匹配索引库中所有记录的数量</li>
<li>TopDocs.scoreDocs：匹配<strong>相关度</strong>高的前边记录数组，scoreDocs的长度小于等于search方法指定的参数n</li>
</ul>
<hr>
<h2 id="相关度排序"><a href="#相关度排序" class="headerlink" title="相关度排序"></a>相关度排序</h2><p>相关度排序是查询结果按照与查询关键字的相关性进行排序，越相关的越靠前。比如搜索”Lucene”关键字，与该关键字最相关的文章应该排在前边。</p>
<p>Lucene对查询关键字和索引文档的相关度进行打分，得分高的就排在前面。这个打分，是在用户进行检索时实时根据搜索的关键字计算出来的，分两步：</p>
<ol>
<li>计算出词(Term)的<strong>权重</strong></li>
<li>根据词的权重值，计算文档相关度得分</li>
</ol>
<p><strong>什么是词的权重</strong>，通过索引部分的学习，明确索引的最小单位是一个Term(索引词典中的一个词)，搜索也是要从Term中搜索，再根据Term找到文档，Term对文档的重要性称为权重，影响Term权重有两个因素：</p>
<ol>
<li>Term Frequency(tf) 指此Term在此文档中出现了多少次，tf越大说明越重要。</li>
</ol>
<p>词(Term)在文档中出现的次数越多，说明此词(Trem)对该文档越重要，如”Lucene”这个词，在文档中出现次数很多，说明该文档主要就是讲Lucene技术的。</p>
<ol>
<li>Document Frequency(df) 指有多少文档包含此Term。df越大说明越不重要。</li>
</ol>
<p>比如，在一篇英文文档中，this出现的次数更多，并不是越重要的，有越多的文档包含此词(Term)，说明此词(Term)太普通，不足以区分这些文档，因而重要性越低。</p>
<h3 id="设置boost值影响相关度排序"><a href="#设置boost值影响相关度排序" class="headerlink" title="设置boost值影响相关度排序"></a>设置boost值影响相关度排序</h3><p><strong>boost是一个加权值(默认加权值为1.0f)，它可以影响权重的计算</strong>。在索引时对某个文档中的field设置加权值高，在搜索时匹配到这个文档就可能排在前面。在搜索对某个域进行加权，在进行组合域查询时，匹配到加权值高的域最后计算的相关度得分就高。<br><strong>设置boost是给域(field)或者Document设置的。</strong></p>
<h4 id="在创建索引时设置"><a href="#在创建索引时设置" class="headerlink" title="在创建索引时设置"></a>在创建索引时设置</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// ...</span></div><div class="line"><span class="comment">// 设置boost值</span></div><div class="line"><span class="keyword">if</span> (book.getId() == <span class="number">4</span>) &#123;</div><div class="line">    description.setBoost(<span class="number">100f</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p><img src="http://om6odecqr.bkt.clouddn.com/%E5%88%9B%E5%BB%BA%E7%B4%A2%E5%BC%95%E6%97%B6%E8%AE%BE%E7%BD%AEboost%E5%80%BC.png" alt="4"></p>
<h4 id="在查询索引时设置"><a href="#在查询索引时设置" class="headerlink" title="在查询索引时设置"></a>在查询索引时设置</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/* 设置前：</span></div><div class="line"><span class="comment">name:mybatis description:mybatis</span></div><div class="line"><span class="comment">总记录数：2</span></div><div class="line"><span class="comment">商品ID：3</span></div><div class="line"><span class="comment">商品名称：mybatis</span></div><div class="line"><span class="comment">商品价格：55.0</span></div><div class="line"><span class="comment">商品图片地址：156156.jpg</span></div><div class="line"><span class="comment">==========================</span></div><div class="line"><span class="comment">商品ID：2</span></div><div class="line"><span class="comment">商品名称：lucene</span></div><div class="line"><span class="comment">商品价格：66.0</span></div><div class="line"><span class="comment">商品图片地址：156156.jpg</span></div><div class="line"><span class="comment">==========================</span></div><div class="line"><span class="comment">*/</span></div><div class="line"><span class="comment">// 在MultiFieldQueryParser创建时设置boost值</span></div><div class="line"><span class="meta">@Test</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMultiFieldQueryParse</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</div><div class="line">    <span class="comment">// 可以指定默认搜索的域是多个</span></div><div class="line">    String[] fields = &#123;<span class="string">"name"</span>,<span class="string">"description"</span>&#125;;</div><div class="line">    Map&lt;String, Float&gt; boosts = <span class="keyword">new</span> HashMap&lt;&gt;();</div><div class="line">    boosts.put(<span class="string">"description"</span>, <span class="number">200f</span>);</div><div class="line">    MultiFieldQueryParser mfParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> StandardAnalyzer(), boosts);</div><div class="line">    Query query = mfParser.parse(<span class="string">"mybatis"</span>);</div><div class="line">    System.out.println(query);<span class="comment">// name:mybatis (description:mybatis)^200.0</span></div><div class="line">    doSearch(query);</div><div class="line">&#125;</div><div class="line"><span class="comment">/* 设置后：</span></div><div class="line"><span class="comment">name:mybatis (description:mybatis)^200.0</span></div><div class="line"><span class="comment">总记录数：2</span></div><div class="line"><span class="comment">商品ID：2</span></div><div class="line"><span class="comment">商品名称：lucene</span></div><div class="line"><span class="comment">商品价格：66.0</span></div><div class="line"><span class="comment">商品图片地址：156156.jpg</span></div><div class="line"><span class="comment">注意这个文档的description中有mybatis</span></div><div class="line"><span class="comment">==========================</span></div><div class="line"><span class="comment">商品ID：3</span></div><div class="line"><span class="comment">商品名称：mybatis</span></div><div class="line"><span class="comment">商品价格：55.0</span></div><div class="line"><span class="comment">商品图片地址：156156.jpg</span></div><div class="line"><span class="comment">==========================</span></div><div class="line"><span class="comment">*/</span></div></pre></td></tr></table></figure>
<hr>
<h2 id="中文分词器"><a href="#中文分词器" class="headerlink" title="中文分词器"></a>中文分词器</h2><p>学过英文的都知道，英文是以单词为单位的，单词与单词之间以空格或者逗号句号隔开。而中文则以字为单位，字又组成词，字和词再组成句子。所以对于英文，我们可以简单以空格判断某个字符串是否为一个单词，比如I love China，love 和 China很容易被程序区分开来；但中文“我爱中国”就不一样了，电脑不知道“中国”是一个词语还是“爱中”是一个词语。把中文的句子切分成有意义的词，就是中文分词，也称切词。我爱中国，分词的结果是：我 爱 中国。</p>
<h3 id="分词器介绍"><a href="#分词器介绍" class="headerlink" title="分词器介绍"></a>分词器介绍</h3><p>lucene自带中文分词器(很弱)：</p>
<p><strong>StandardAnalyzer</strong>，单词分词就是按照中文一个字一个字地进行分词。如：我爱中国，效果是：”我”,”爱”,”中”,”国”</p>
<p><strong>CJKAnalyzer</strong>，二分法分词按两个字进行切分。如：”我是中国人”，效果：”我是”,”是中”,”中国”,”国人”。</p>
<p>第三方中文分词器(十款java开源中文分词组件<a href="https://segmentfault.com/a/1190000010015884)：" target="_blank" rel="external">https://segmentfault.com/a/1190000010015884)：</a></p>
<table>
<thead>
<tr>
<th style="text-align:left">名称</th>
<th style="text-align:left">地址</th>
<th style="text-align:left">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">paoding</td>
<td style="text-align:left"><a href="https://code.google.com/p/paoding/" target="_blank" rel="external">https://code.google.com/p/paoding/</a></td>
<td style="text-align:left">最新提交的代码在 2008-06-03，在svn中最新也是2010年提交，已经过时，不予考虑。</td>
</tr>
<tr>
<td style="text-align:left">mmseg4j</td>
<td style="text-align:left"><a href="https://github.com/chenlb/mmseg4j-solr" target="_blank" rel="external">https://github.com/chenlb/mmseg4j-solr</a></td>
<td style="text-align:left">支持最新lucene/solr6.0.0，有较大活跃度，用了mmseg算法。</td>
</tr>
<tr>
<td style="text-align:left">IK-analyzer</td>
<td style="text-align:left"><a href="http://git.oschina.net/wltea/IK-Analyzer-2012FF" target="_blank" rel="external">http://git.oschina.net/wltea/IK-Analyzer-2012FF</a></td>
<td style="text-align:left">是一个非常著名和老牌的 Java 中文分词库，目前 OSChina 网站也是使用 IK 分词器。IKAnalyzer 的作者 @林良益 已经将项目源码托管到 Git@OSC 平台，但该项目在几年前已经停止更新</td>
</tr>
<tr>
<td style="text-align:left">ansj_seg</td>
<td style="text-align:left"><a href="https://github.com/NLPchina/ansj_seg" target="_blank" rel="external">https://github.com/NLPchina/ansj_seg</a></td>
<td style="text-align:left">并未说明是否支持Lucene，是一个由CRF（条件随机场）算法所做的分词算法。</td>
</tr>
<tr>
<td style="text-align:left">imdict-chinese-analyzer</td>
<td style="text-align:left"><a href="https://code.google.com/p/imdict-chinese-analyzer/" target="_blank" rel="external">https://code.google.com/p/imdict-chinese-analyzer/</a></td>
<td style="text-align:left">中科院分词工具，貌似只支持Lucene 3以前。是利用HMM（隐马尔科夫链）算法</td>
</tr>
<tr>
<td style="text-align:left">Jcseg</td>
<td style="text-align:left"><a href="http://git.oschina.net/lionsoul/jcseg" target="_blank" rel="external">http://git.oschina.net/lionsoul/jcseg</a></td>
<td style="text-align:left">是基于mmseg算法的一个轻量级中文分词器，作者有较高的活跃度。</td>
</tr>
</tbody>
</table>
<h3 id="使用中文分词器IKAnalyzer"><a href="#使用中文分词器IKAnalyzer" class="headerlink" title="使用中文分词器IKAnalyzer"></a>使用中文分词器IKAnalyzer</h3><p>IKAnalyzer继承Lucene的Analyzer抽象类，使用IKAnalyzer和Lucene自带的分析器方法一样，将Analyzer测试代码改为IKAnalyzer测试中文分词效果。<strong>如果使用中文分词器ik-analyzer，就在索引和搜索程序中使用一致的分词器ik-analyzer</strong>。</p>
<p>基于最新的Lucene-6.6.0进行学习，很多方法都过时并不适用了，你需要下载民间适合Lucene的IKAnalyzer<br>链接：等待上传<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 创建分词器——IKAnalyzer分词器</span></div><div class="line">Analyzer analyzer = <span class="keyword">new</span> IKAnalyzer();</div><div class="line"><span class="comment">// Console:</span></div><div class="line"><span class="comment">// 加载扩展词典：ext.dic</span></div><div class="line"><span class="comment">// 加载扩展停止词典：stopword.dic</span></div></pre></td></tr></table></figure></p>
<p>IKAnalyzer分词器强大之处在于可以拓展中文词库，从ikanalyzer包中拷贝配置文件到classpath下：<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">&lt;!-- IKAnalyzer.cfg.xml --&gt;</span></div><div class="line">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</div><div class="line"><span class="meta">&lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;</span>  </div><div class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span>  </div><div class="line">	<span class="tag">&lt;<span class="name">comment</span>&gt;</span>IK Analyzer 扩展配置<span class="tag">&lt;/<span class="name">comment</span>&gt;</span></div><div class="line">	<span class="comment">&lt;!--用户可以在这里配置自己的扩展字典 --&gt;</span></div><div class="line">	<span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">"ext_dict"</span>&gt;</span>dicdata/mydict.dic<span class="tag">&lt;/<span class="name">entry</span>&gt;</span> </div><div class="line">	<span class="comment">&lt;!--用户可以在这里配置自己的扩展停止词字典--&gt;</span></div><div class="line">	<span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">"ext_stopwords"</span>&gt;</span>dicdata/stopword.dic<span class="tag">&lt;/<span class="name">entry</span>&gt;</span> </div><div class="line">	</div><div class="line"><span class="tag">&lt;/<span class="name">properties</span>&gt;</span></div></pre></td></tr></table></figure></p>
<p>如果想配置扩展词和停用词，就创建扩展词的文件和停用词的文件，文件的编码要是utf-8。<br><strong>注意：不要用记事本保存扩展词文件和停用词文件，那样的话，格式中是含有bom的。</strong></p>

        </div>

        <blockquote class="post-copyright">
    <div class="content">
        
<span class="post-time">
    最后更新时间：<time datetime="2017-12-05T09:58:29.758Z" itemprop="dateUpdated">2017年12月5日 17:58</time>
</span><br>


        如要转载请注明出处：<a href="/2017/09/02/Lucene6.6.0_primary_01/" target="_blank" rel="external">http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/</a>
    </div>
    <footer>
        <a href="http://magic_duck.oschina.io">
            <img src="/img/avatar.jpg" alt="神奇的鸭鸭">
            神奇的鸭鸭
        </a>
    </footer>
</blockquote>

        
<div class="page-reward">
    <a id="rewardBtn" href="javascript:;" class="page-reward-btn waves-effect waves-circle waves-light">赏</a>
</div>



        <div class="post-footer">
            
	<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/全文检索/">全文检索</a></li></ul>


            
<div class="page-share-wrap">
    

<div class="page-share" id="pageShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&title=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&pic=http://magic_duck.oschina.io/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&title=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&source=" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&via=http://magic_duck.oschina.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>



    <a href="javascript:;" id="shareFab" class="page-share-fab waves-effect waves-circle">
        <i class="icon icon-share-alt icon-lg"></i>
    </a>
</div>



        </div>
    </div>

    
<nav class="post-nav flex-row flex-justify-between">
  
    <div class="waves-block waves-effect prev">
      <a href="/2017/09/04/solr6.6.0_exception_01/" id="post-prev" class="post-nav-link">
        <div class="tips"><i class="icon icon-angle-left icon-lg icon-pr"></i> Prev</div>
        <h4 class="title">solr6.6.0异常</h4>
      </a>
    </div>
  

  
    <div class="waves-block waves-effect next">
      <a href="/2017/08/21/JavaWeb存储数据到数据库乱码问题/" id="post-next" class="post-nav-link">
        <div class="tips">Next <i class="icon icon-angle-right icon-lg icon-pl"></i></div>
        <h4 class="title">JavaWeb存储数据到数据库乱码问题</h4>
      </a>
    </div>
  
</nav>



    







</article>

<div id="reward" class="page-modal reward-lay">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <h3 class="reward-title">
        <i class="icon icon-quote-left"></i>
        我只要一角钱~ ~
        <i class="icon icon-quote-right"></i>
    </h3>
    <ul class="reward-items">
        
        <li>
            <img src="/img/wechat.png" title="微信打赏二维码" alt="微信打赏二维码">
            <p>微信</p>
        </li>
        

        
        <li>
            <img src="/img/alipay.jpg" title="支付宝打赏二维码" alt="支付宝打赏二维码">
            <p>支付宝</p>
        </li>
        
    </ul>
</div>



</div>

        <footer class="footer">
    <div class="top">
        
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        站点总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        站点总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


        <p>
            <span><a href="" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>
            <span>博客内容遵循 <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0协议</a></span>
        </p>
    </div>
    <div class="bottom">
        <p>
            <span>Power by <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://git.oschina.net/z77z" target="_blank">邹海清</a></span>
            <span>神奇的鸭鸭の码农库 &copy; 2017</span>
        </p>
    </div>
</footer>

    </main>
    <div class="mask" id="mask"></div>
<a href="javascript:;" id="gotop" class="waves-effect waves-circle waves-light"><span class="icon icon-lg icon-chevron-up"></span></a>



<div class="global-share" id="globalShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&title=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&pic=http://magic_duck.oschina.io/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&title=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&source=" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《全文检索技术Lucene6.6.0》 — 神奇的鸭鸭の码农库&url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/&via=http://magic_duck.oschina.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>


<div class="page-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <p>扫一扫，分享到微信</p>
    <img src="//api.qrserver.com/v1/create-qr-code/?data=http://magic_duck.oschina.io/2017/09/02/Lucene6.6.0_primary_01/" alt="微信分享二维码">
</div>




    <script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>
<script>
var BLOG = { ROOT: '/', SHARE: true, REWARD: true };



lazyScripts.push('//s95.cnzz.com/z_stat.php?id=1261081671&web_id=1261081671')

</script>

<script src="/js/main.min.js?v=1.4.3"></script>


<div class="search-panel" id="search-panel">
    <ul class="search-result" id="search-result"></ul>
</div>
<template id="search-tpl">
<li class="item">
    <a href="{path}" class="waves-block waves-effect">
        <div class="title ellipsis" title="{title}">{title}</div>
        <div class="flex-row flex-middle">
            <div class="tags ellipsis">
                {tags}
            </div>
            <time class="flex-col time">{date}</time>
        </div>
    </a>
</li>
</template>

<script src="/js/search.min.js?v=1.4.3" async></script>






<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>


</body>
</html>
